package cn.hsw.platform.core.moudle.setvalue;


import cn.hsw.platform.core.util.SpringContextUtil;
import cn.hsw.platform.core.util.Validator;
import lombok.SneakyThrows;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;

/**
 * 给类的字段赋值
 * @author 李子木
 * @date 2020-11-27
 */
@Component
@Aspect
public class SetValueAspect {

    @AfterReturning(value = "@annotation(cn.hsw.platform.core.moudle.setvalue.NeedSetValue)",returning = "ret")
    public Object doSetValue(Object ret){

        //如果是page 获取page中的list
        if(ret instanceof Page){
            setValueForCollection(((Page<?>) ret).getContent());
        }
        //如果是集合
        if(ret instanceof Collection){
            setValueForCollection((Collection) ret);
        }else{
            //不是集合变成集合
            setValueForCollection(Collections.singletonList(ret));
        }

        return ret;
    }


    @SneakyThrows
    private void setValueForCollection(Collection col){

        //判断集合是否有值
        if(!col.iterator().hasNext()){
            return ;
        }
        //获取注解列 Collection ->class -> filed -> @SetValue filed

        //找到实体类
        Class<?> clazz = col.iterator().next().getClass();

        //实体类的字段
        Field[] fields = clazz.getDeclaredFields();

        //参数字段
        Field paramField = null;

        //循环实体类字段找到需要赋值的列
        for (Field field:fields) {
            SetValue setValue = field.getAnnotation(SetValue.class);
            //没有@SetValue 直接下次循环
            if(Validator.isNull(setValue)){
                continue;
            }
            field.setAccessible(true);

            //拿到要调用的bean
            Object bean = SpringContextUtil.getBean(setValue.beanClass());

            //拿到参数列
            if(Validator.isNull(paramField)){
                try {
                    paramField = clazz.getDeclaredField(setValue.param());
                }catch (NoSuchFieldException e) {
                    paramField = clazz.getSuperclass().getDeclaredField(setValue.param());
                }
            }



            //拿到要调用的方法
            Method method = setValue.beanClass().getMethod(setValue.method(),paramField.getType());

            paramField.setAccessible(true);

            //遍历结果对象，挨个赋值
            Field targetField = null;
            for(Object obj:col){
                //获取参数值
                Object paramValue = paramField.get(obj);
                if(Validator.isNull(paramValue)){
                    continue;
                }
                //调用方法
                Object value = method.invoke(bean,paramValue);

                //判断target是否有值，有值则去获取返回值里面某个字段，没有则不执行
                if(Validator.isNotEmpty(setValue.target())){
                    if(Validator.isNotNull(value)){
                        if(Validator.isNotEmpty(targetField)){
                            targetField = value.getClass().getDeclaredField(setValue.target());
                        }
                        targetField.setAccessible(true);
                        value = targetField.get(value);
                    }
                }
                if(Validator.isNotNull(value)){
                    //赋值
                    field.set(obj,value);
                }
            }


        }

    }
}
